package com.regent.central.bill.service.bean;

import com.github.pagehelper.PageHelper;
import com.regent.central.bill.core.Delivery;
import com.regent.central.bill.core.SaleOrderAction;
import com.regent.central.bill.dto.delivery.*;
import com.regent.central.bill.repository.DeliveryMapper;
import com.regent.central.bill.service.*;
import com.regent.central.infrastructure.service.bean.DomainServiceBean;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.lang.reflect.Array;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class DeliveryOrderServiceBean extends DomainServiceBean<DeliveryMapper, Delivery> implements DeliveryOrderService {
    @Resource
    private SaleOrderActionService saleOrderActionService;
    @Resource
    private DeliveryGoodsService deliveryGoodsService;
    @Resource
    private DeliveryActionService deliveryActionService;
    @Resource
    private SaleOrderService saleOrderService;

    /**
     * 获取发货动作列表
     *
     * @param unitId
     * @param keyword
     * @param empIds
     * @param startSearchTime
     * @param startTime
     * @param endTime
     * @param pageNo
     * @param pageSize
     * @return
     */
    @Override
    public List<DeliveryOrderDTO> getDeliveryOrder(String unitId, String keyword, List<String> empIds, String startSearchTime, String startTime, String endTime, int pageNo, int pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        return mapper.getDeliveryOrder(unitId, keyword, empIds, startSearchTime, startTime, endTime);
    }

    /**
     * 发货单详情
     *
     * @param deliveryOrderId
     * @return
     */
    @Override
    public DeliveryDetailDTO getDeliveryOrderDetail(String deliveryOrderId) {
        return mapper.getDeliveryOrderDetail(deliveryOrderId);
    }

    /**
     * 发货单操作记录
     *
     * @param deliveryOrderId
     * @return
     */
    @Override
    public List<DeliveryRecordDTO> getDeliveryOrderRecord(String deliveryOrderId) {
        return mapper.getDeliveryOrderRecord(deliveryOrderId);
    }

//    /**
//     * 获取该日期最后一个发货单
//     * @param unitId
//     * @param deliveryDay
//     * @return
//     */
//    @Override
//    public Delivery getLastRecordByDate(String unitId, String deliveryDay) {
//        return mapper.getLastRecordByDate(unitId,deliveryDay);
//    }

    @Override
    public Integer getMaxDeliveryNoByDate(String unitId, String deliveryDay) {
        return mapper.getMaxDeliveryNoByDate(unitId, deliveryDay);
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    public void revoke(String deliveryOrderId, String userId) {
        List<SaleOrderAction> saleOrderDeliveryActions = saleOrderActionService.getSaleOrderDeliveryActions(deliveryOrderId);
        saleOrderDeliveryActions.forEach(action -> {
            // 撤销
            saleOrderActionService.cancel(action.getActionId(), userId);
            // 撤销销售单的发货货品操作记录
            String saleOrderId = action.getCentralBillSaleOrderId();
            List<SaleOrderAction> actions = saleOrderActionService.getSaleOrderDeliveryGoodsActions(
                    saleOrderId,
                    deliveryOrderId
            );
            actions.forEach(act -> saleOrderActionService.cancel(act.getId(), userId));
            String[] deliveryGoodsIds = actions.stream().map(SaleOrderAction::getActionId).collect(Collectors.toList()).toArray(new String[0]);
            // 撤销发货单的该销售单的发货货品记录
            deliveryGoodsService.cancel(userId, deliveryGoodsIds);
            deliveryActionService.cancel(deliveryOrderId, userId, deliveryGoodsIds);

            //@TODO 重新计算销售单二级数据
            // 撤销
            //saleOrderActionService.cancel(request.getActionId(),userId);
            //作废发货单
            canceledDeliveryOrder(deliveryOrderId, userId);
        });
    }

    @Override
    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
    public void canceledDeliveryOrder(String deliveryOrderId, String userId) {
        mapper.canceledDeliveryOrder(deliveryOrderId, userId);
    }

    @Override
    public List<DeliverySaleOrderDTO> getEditSaleOrders(String deliveryOrderId, String unitId, String customerId, String startSearchTime, String startTime, String endTime, String sortBy, Integer sortAs) {
        List<DeliverySaleOrderDTO> owedSaleOrders = saleOrderService.getOwedSaleOrders(
                unitId,
                customerId,
                startSearchTime,
                startTime,
                endTime,
                sortBy,
                sortAs,
                null,
                1,
                1
        );
        DeliveryDetailDTO deliveryOrderDetail = getDeliveryOrderDetail(deliveryOrderId);
        if (owedSaleOrders == null || deliveryOrderDetail == null) {
            return null;
        }

        List<DeliveryDetailSaleOrderDTO> orders = deliveryOrderDetail.getOrders();
        List<DeliverySaleOrderDTO> addOrders = new ArrayList<DeliverySaleOrderDTO>();
        List<DeliverySaleOrderStyleDTO> addStyles = null;
        List<DeliverySaleOrderStyleSKUDTO> addSkus = null;

        DeliverySaleOrderStyleDTO addStyle = null;
        DeliverySaleOrderStyleSKUDTO addSku = null;

        BigDecimal styleTotalNum = null;

        for (DeliveryDetailSaleOrderDTO order : orders) {
            DeliverySaleOrderDTO sameOrder = getSameOrderById(owedSaleOrders, order.getSaleOrderId());
            if (sameOrder == null) {
                DeliverySaleOrderDTO addOrder = new DeliverySaleOrderDTO();
                addOrder.setCustomerId(customerId);
                //TODO  欠款
                addOrder.setAmountDebt(BigDecimal.ZERO);
                //TODO  欠货
                addOrder.setTotalOwed(BigDecimal.ZERO);
                addOrder.setOrderNo(order.getOrderNo());
                addOrder.setOrderDay(order.getDateOrdered());
                addOrder.setSaleOrderId(order.getSaleOrderId());
                List<DeliveryDetailStyleDTO> styles = order.getStyles();
                addStyles = new ArrayList<>();
                for (DeliveryDetailStyleDTO style : styles) {
                    addStyle = new DeliverySaleOrderStyleDTO();
                    addStyle.setGoodsId(style.getGoodsId());
                    addStyle.setStyleId(style.getStyleId());
                    List<DeliveryDetailStyleSKUDTO> skus = style.getSkus();
                    addSkus = new ArrayList<>();
                    for (DeliveryDetailStyleSKUDTO sku : skus) {
                        styleTotalNum = styleTotalNum.add(sku.getQuantity());
                        addSku = new DeliverySaleOrderStyleSKUDTO();
                        addSku.setSkuId(sku.getSkuId());
                        addSku.setQuantity(sku.getQuantity());
                        addSku.setPrice(sku.getPrice());
                        addSkus.add(addSku);
                    }
                    addStyle.setTotal(styleTotalNum);
                    addStyle.setSkus(addSkus);
                }
                addOrder.setStyles(addStyles);
                addOrders.add(addOrder);
            } else {
                List<DeliverySaleOrderStyleDTO> SaleOrderStyles = sameOrder.getStyles();
                List<DeliveryDetailStyleDTO> styles = order.getStyles();
                for (DeliveryDetailStyleDTO style : styles) {
                    DeliverySaleOrderStyleDTO sameStyle = getSameStyleById(SaleOrderStyles, style.getStyleId());
                    if (sameStyle == null) {
                        addStyle = new DeliverySaleOrderStyleDTO();
                        addStyle.setGoodsId(style.getGoodsId());
                        addStyle.setStyleId(style.getStyleId());
                        List<DeliveryDetailStyleSKUDTO> skus = style.getSkus();
                        addSkus = new ArrayList<>();
                        for (DeliveryDetailStyleSKUDTO sku : skus) {
                            styleTotalNum = styleTotalNum.add(sku.getQuantity());
                            addSku = new DeliverySaleOrderStyleSKUDTO();
                            addSku.setSkuId(sku.getSkuId());
                            addSku.setQuantity(sku.getQuantity());
                            addSku.setPrice(sku.getPrice());
                            addSkus.add(addSku);
                        }
                        addStyle.setTotal(styleTotalNum);
                        addStyle.setSkus(addSkus);
                        SaleOrderStyles.add(addStyle);
                    } else {
                        BigDecimal total = sameStyle.getTotal();

                        List<DeliverySaleOrderStyleSKUDTO> saleOrderStyleSkus = sameStyle.getSkus();
                        List<DeliveryDetailStyleSKUDTO> skus = style.getSkus();
                        for (DeliveryDetailStyleSKUDTO sku : skus) {
                            DeliverySaleOrderStyleSKUDTO sameSku = getSameSkuById(saleOrderStyleSkus, sku.getSkuId());
                            if (sameSku == null) {
                                addSku = new DeliverySaleOrderStyleSKUDTO();
                                addSku.setSkuId(sku.getSkuId());
                                addSku.setQuantity(sku.getQuantity());
                                addSku.setPrice(sku.getPrice());
                                saleOrderStyleSkus.add(addSku);
                            } else {
                                sameSku.setQuantity(sameSku.getQuantity().add(sku.getQuantity()));
                            }
                            total = total.add(sku.getQuantity());
                        }
                        sameStyle.setTotal(total);
                    }
                }
            }
        }
        owedSaleOrders.addAll(addOrders);


        return owedSaleOrders;
    }

    public DeliverySaleOrderDTO getSameOrderById(List<DeliverySaleOrderDTO> orders, String orderId) {
        for (DeliverySaleOrderDTO order : orders) {
            String saleOrderId = order.getSaleOrderId();
            if (saleOrderId.equals(orderId)) {
                return order;
            }
        }
        return null;
    }

    public DeliverySaleOrderStyleDTO getSameStyleById(List<DeliverySaleOrderStyleDTO> styles, String styleId) {
        for (DeliverySaleOrderStyleDTO style : styles) {
            String saleStyleId = style.getStyleId();
            if (saleStyleId.equals(styleId)) {
                return style;
            }
        }
        return null;
    }

    public DeliverySaleOrderStyleSKUDTO getSameSkuById(List<DeliverySaleOrderStyleSKUDTO> skus, String skuId) {
        for (DeliverySaleOrderStyleSKUDTO sku : skus) {
            String saleSkuId = sku.getSkuId();
            if (saleSkuId.equals(skuId)) {
                return sku;
            }
        }
        return null;
    }

    ;


//    @Override
//    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRED, rollbackFor = Throwable.class)
//    public void revokeAction(String deliveryOrderId, String saleOrderId) {
//        mapper.revokeAction(deliveryOrderId, saleOrderId);
//    }

}
